#include "stdafx.h"
#include "EffectParams.h"

#include "Exception.h"
#include "Effect.h"

namespace Cvekas {

EffectParams::EffectParams(Effect* owner)
	: owner(owner)
{
	assert(owner);
}

EffectParams::~EffectParams()
{
}

// Static, name indexing:

void EffectParams::add(const std::string& name, float value)
{
	Param<DWordValue> param = constructParam<DWordValue>(name);
	param.value.float_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(const std::string& name, int value)
{
	Param<DWordValue> param = constructParam<DWordValue>(name);
	param.value.int_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(const std::string& name, bool value)
{
	Param<DWordValue> param = constructParam<DWordValue>(name);
	param.value.bool_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(const std::string& name, const Vector2& value)
{
	Param<Vector2> param = constructParam<Vector2>(name);
	param.value = value;
	vector2_params.push_back(param);
}

void EffectParams::add(const std::string& name, const Vector3& value)
{
	Param<Vector3> param = constructParam<Vector3>(name);
	param.value = value;
	vector3_params.push_back(param);
}

void EffectParams::add(const std::string& name, const Vector4& value)
{
	Param<Vector4> param = constructParam<Vector4>(name);
	param.value = value;
	vector4_params.push_back(param);
}

void EffectParams::add(const std::string& name, const Matrix& value)
{
	Param<Matrix> param = constructParam<Matrix>(name);
	param.value = value;
	matrix_params.push_back(param);
}

void EffectParams::add(const std::string& name, TexturePtr value)
{
	Param<TexturePtr> param = constructParam<TexturePtr>(name);
	param.value = value;
	texture_params.push_back(param);
}

// Static, handle indexing:

void EffectParams::add(ParamHandle handle, float value)
{
	Param<DWordValue> param = constructParam<DWordValue>(handle);
	param.value.float_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, int value)
{
	Param<DWordValue> param = constructParam<DWordValue>(handle);
	param.value.int_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, bool value)
{
	Param<DWordValue> param = constructParam<DWordValue>(handle);
	param.value.bool_val = value;
	dword_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, const Vector2& value)
{
	Param<Vector2> param = constructParam<Vector2>(handle);
	param.value = value;
	vector2_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, const Vector3& value)
{
	Param<Vector3> param = constructParam<Vector3>(handle);
	param.value = value;
	vector3_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, const Vector4& value)
{
	Param<Vector4> param = constructParam<Vector4>(handle);
	param.value = value;
	vector4_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, const Matrix& value)
{
	Param<Matrix> param = constructParam<Matrix>(handle);
	param.value = value;
	matrix_params.push_back(param);
}

void EffectParams::add(ParamHandle handle, TexturePtr value)
{
	Param<TexturePtr> param = constructParam<TexturePtr>(handle);
	param.value = value;
	texture_params.push_back(param);
}

// Dynamic, name indexing:

void EffectParams::addDynamic(const std::string& name, const float* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const int* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const bool* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const Vector2* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 8;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const Vector3* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 12;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const Vector4* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 16;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const Matrix* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(name);
	param.value.size = 64;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(const std::string& name, const TexturePtr* value)
{
	Param<const TexturePtr*> param = constructParam<const TexturePtr*>(name);
	param.value = value;
	texture_ptr_params.push_back(param);
}

// Dynamic, handle indexing:

void EffectParams::addDynamic(ParamHandle handle, const float* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const int* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const bool* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 4;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const Vector2* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 8;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const Vector3* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 12;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const Vector4* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 16;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const Matrix* value)
{
	Param<PtrValue> param = constructParam<PtrValue>(handle);
	param.value.size = 64;
	param.value.ptr = value;
	ptr_params.push_back(param);
}

void EffectParams::addDynamic(ParamHandle handle, const TexturePtr* value)
{
	Param<const TexturePtr*> param = constructParam<const TexturePtr*>(handle);
	param.value = value;
	texture_ptr_params.push_back(param);
}


void EffectParams::applyParams()
{
	for(uint i = 0; i < dword_params.size(); ++i)
		owner->setParamValue(dword_params[i].handle, &dword_params[i].value.int_val, 4);
	
	for(uint i = 0; i < vector2_params.size(); ++i)
		owner->setParamValue(vector2_params[i].handle, &vector2_params[i].value, 8);

	for(uint i = 0; i < vector3_params.size(); ++i)
		owner->setParamValue(vector3_params[i].handle, &vector3_params[i].value, 12);

	for(uint i = 0; i < vector4_params.size(); ++i)
		owner->setParamValue(vector4_params[i].handle, &vector4_params[i].value, 16);

	for(uint i = 0; i < matrix_params.size(); ++i)
		owner->setParamValue(matrix_params[i].handle, &matrix_params[i].value, 64);
	
	for(uint i = 0; i < texture_params.size(); ++i)
		owner->setParamValue(texture_params[i].handle, texture_params[i].value);

	for(uint i = 0; i < ptr_params.size(); ++i)
		owner->setParamValue(ptr_params[i].handle, ptr_params[i].value.ptr, ptr_params[i].value.size);

	for(uint i = 0; i < texture_ptr_params.size(); ++i)
		owner->setParamValue(texture_ptr_params[i].handle, *texture_ptr_params[i].value);

	//owner->commitChanges();
}

// Checks if parameter is not already added
void EffectParams::checkParam(ParamHandle handle)
{
#ifdef _DEBUG
	for(uint i = 0; i < dword_params.size(); ++i)
		if(dword_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < vector2_params.size(); ++i)
		if(vector2_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < vector3_params.size(); ++i)
		if(vector3_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < vector4_params.size(); ++i)
		if(vector4_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < matrix_params.size(); ++i)
		if(matrix_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < texture_params.size(); ++i)
		if(texture_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < ptr_params.size(); ++i)
		if(ptr_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

	for(uint i = 0; i < texture_ptr_params.size(); ++i)
		if(texture_ptr_params[i].handle == handle)
			throw EXCEPTION("Parameter already added to this EffectParams instance");

#endif
}

} // namespace